package cn.tedu.lbs.basic.web.filters;

import cn.tedu.lbs.basic.web.utils.AuthenticationContextUtil;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.common.passport.encoder.JwtEncoder;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 当前项目 作为 入口 对请求 头Authorizaiton
 * 进行jwt解析的 向后传递解析结果的 认证过滤器逻辑
 */
@Slf4j
@Component
public class AuthenticationFilter implements Filter {
    @Autowired
    private JwtEncoder<UserPrinciple> jwtDecoder;
    /**
     * servlet过滤器执行过滤的核心方法
     * 案例1: 让这个过滤器的过滤代码生效 看到过滤效果 请求经过这个过滤器
     * @param request 请求对象 Servlet协议请求 当前环境一定是HttpServletRequest
     * @param response 请求对象 Servlet协议响应 当前环境一定是HttpServletResponse 如果用过滤器拦截
     *                 相当于使用这个response输出数据
     * @param chain 连接整体过滤器的一个 管道对象 -- 过滤连
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("认证过滤器 解析jwt 获取认证对象");
        //获取当前线程对象
        //Thread thread = Thread.currentThread();
        //log.info("认证过滤器 执行线程对象:{},id",thread,thread.getId());
        UserPrinciple userPrinciple = null;
        if (request instanceof HttpServletRequest){
            //http请求
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            //取头 Authorization
            String jwt = httpServletRequest.getHeader("Authorization");
            if (jwt!=null&&jwt.length()>0){
                try {
                    //jwtEncoder解析jwt获取 userPrinciple
                    userPrinciple=jwtDecoder.getLoginFromToken(jwt,UserPrinciple.class);
                } catch (BusinessException e) {
                    log.error("jwt解析失败",e);
                }
            }
        }
        //过滤器 执行下游代码逻辑之前,要想办法将userPrinciple向后传递
        AuthenticationContextUtil.save(userPrinciple);//null 正确完成解析对象
        request.setAttribute("userPrinciple",userPrinciple);
        //调用过滤链对象 将请求和响应对象 向后输出传递 流程继续
        chain.doFilter(request,response);
        //响应即将返回 请求即将结束,释放本次请求处理线程的数据
        AuthenticationContextUtil.clear();
        request.removeAttribute("userPrinciple");
    }
}
